﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Threading;
using MayhemCore;
using System.Diagnostics;


namespace Total_Mayhem.Common
{
    public static class Misc
    {
        public static string FileName = AppDataDirectory + "\\mayhem.txt";
        public static System.IO.StreamWriter LogFile = System.IO.File.AppendText(FileName);

        public static void WriteLog(String strFormattedMessage, params object[] args)
        {
            string Message = string.Format("[{1} {0}] ", GetCallStackString(), DateTime.Now.ToShortTimeString()) + string.Format(strFormattedMessage, args); 
            Debug.WriteLine(Message);
            LogFile.WriteLine(Message);
        }

        public static void WriteLog(string strMessage, Exception ex = null)
        {
            string Message;
            if (ex == null)
            {
                Message = string.Format("[{1} {0}] {2}", GetCallStackString(), DateTime.Now.ToShortTimeString(), strMessage);
                Debug.WriteLine(Message);
                LogFile.WriteLine(Message);    
            }
            else
            {
                Message = string.Format("[{1} {0}] ERROR: {2}\r\nMessage:", GetCallStackString(), DateTime.Now.ToShortTimeString(), strMessage, ex.Message);
                MayhemCore.Logger.WriteLine(Message);
                LogFile.WriteLine(Message);
                MayhemCore.ErrorLog.AddError(ErrorType.Failure, string.Format("Exception thrown at {0}. See Log file at {1}.", GetCallStackString(), FileName));
                System.Windows.MessageBox.Show(string.Format("Exception thrown at {0}. See Log file at {1}.", GetCallStackString(), FileName));
            }
        }

        private static string GetCallStackString()
        {
            StackTrace stackTrace = new StackTrace();
            StackFrame frame = stackTrace.GetFrame(2);
            string callingClass = frame.GetMethod().DeclaringType.Name;
            string callingMethod = frame.GetMethod().Name;
            return callingClass + "." + callingMethod;
        }

        static public string AssemblyDirectory
        {
            get
            {
                string codeBase = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
                UriBuilder uri = new UriBuilder(codeBase);
                string path = Uri.UnescapeDataString(uri.Path);
                return System.IO.Path.GetDirectoryName(path);
            }
        }

        static public string AppDataDirectory
        {
            get
            {
                return Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
            }
        }

        public static Process ExecuteNirCmd(string Arguments)
        {
            try
            {
                WriteLog("Arguments: {0}", Arguments);
                string strPath = String.Format("{0}\\nircmd\\nircmd.exe", AssemblyDirectory);
                
                if (System.IO.File.Exists(strPath))
                {
                    return Process.Start(strPath, Arguments);
                }
                else
                {
                    System.Windows.MessageBox.Show("Error: Cannot find file " + strPath);
                    WriteLog("Error: Cannot find file " + strPath);
                }
            }
            catch (Exception ex) {
                WriteLog("Error trying to run NirCmd.", ex);
            }
            return null;
        }
    }

    public static class DispatcherExtensions
    {

        /// <summary>
        /// Extension method for delaying invocation of a method on the Dispatcher thread.
        /// </summary>
        /// <param name="d"></param>
        /// <param name="Delay"></param>
        /// <param name="Method"></param>
        public static void DelayInvoke(this System.Windows.Threading.Dispatcher d, TimeSpan Delay, Action Method){
            System.Threading.ThreadPool.QueueUserWorkItem(func => 
                { 
                    System.Threading.Thread.Sleep(Delay);
                    System.Windows.Threading.Dispatcher.CurrentDispatcher.Invoke(Method, DispatcherPriority.Send, null);
                });
        }
    }
}

